/**
 * @file crtsurfdata2.cpp
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2024-04-19
 *
 * @copyright Copyright (c) 2024
 *
 */
#include <iostream>
#include "../../public/_public.h"
#include <vector>

// 站点参数数据
struct st_stcode
{
    /* data */
    char provname[31]; // 省
    char obtid[11];    // 站号
    char obtname[31];  // 站名
    double lat;        // 纬度
    double lon;        // 经度
    double height;     // 海拔高度
};

// 气象数据
struct st_surfdata
{
    char obtid[11];     // 站点代码。
    char ddatetime[21]; // 数据时间：格式yyyymmddhh24miss
    int t;              // 气温：单位，0.1摄氏度。
    int p;              // 气压：0.1百帕。
    int u;              // 相对湿度，0-100之间的值。
    int wd;             // 风向，0-360之间的值。
    int wf;             // 风速：单位0.1m/s
    int r;              // 降雨量：0.1mm。
    int vis;            // 能见度：0.1米。
};

CLogFile logfile;
CFile File;
CPActive pactive;
std::vector<struct st_stcode> vstcode;
std::vector<struct st_surfdata> vsurfdata;
char strddatetime[21];

/**
 * @brief 加载站点参数
 *
 * @param inifile 站点参数文件，建议使用绝对路径
 * @return true
 * @return false
 */
// 把站点参数文件中加载到vstcode容器中。
bool LoadSTCode(const char *inifile);

// 模拟生成全国气象站点分钟观测数据，存放在vsurfdata容器中。
void CrtSurfData();

// 把容器vsurfdata中的全国气象站点分钟观测数据写入文件。
bool CrtSurfFile(const char *outpath, const char *datafmt);

void handle(int sig);

int main(int argc, char *argv[])
{
    signal(2, handle);
    signal(15, handle);
    pactive.AddPInfo(2,"crtsurfdata");  

    // 参>4
    //!(AB)=!A+!B
    if (argc != 5 && argc != 6)
    {
        // 不能
        printf("Using:./crtsurfdata inifile outpath logfile datafmt [datetime]\n");
        printf("Example:/project/idc1/bin/crtsurfdata /project/idc1/ini/stcode.ini /tmp/idc/surfdata /log/idc/crtsurfdata.log xml,json,csv\n");
        printf("        /project/idc1/bin/crtsurfdata /project/idc1/ini/stcode.ini /tmp/idc/surfdata /log/idc/crtsurfdata.log xml,json,csv 20210710123000\n");
        printf("        /project/tools1/bin/procctl 60 /project/idc1/bin/crtsurfdata /project/idc1/ini/stcode.ini /tmp/idc/surfdata /log/idc/crtsurfdata.log xml,json,csv\n\n\n");

        printf("inifile  全国气象站点参数文件名。\n");
        printf("outpath  全国气象站点数据文件存放的目录。\n");
        printf("logfile  本程序运行的日志文件名。\n");
        printf("datafmt  生成数据文件的格式，支持xml、json和csv三种格式，中间用逗号分隔。\n");
        printf("datetime 这是一个可选参数，表示生成指定时间的数据和文件。\n\n\n");
        return -1;
    }

    memset(strddatetime, 0, sizeof(strddatetime));
    if (argc == 5)
        LocalTime(strddatetime, "yyyymmddhh24miss");
    else
        STRCPY(strddatetime, sizeof(strddatetime), argv[5]);

    // 日志文件写东西。打开日志
    if (logfile.Open(argv[3], "a+", false))
    {
        // 写日志
        logfile.Write("第一次记录日志\n");
        logfile.WriteEx("第一次记录日志\n");

        if (LoadSTCode(argv[1]))
        {
            std::cout << "加载完成\n"
                      << std::endl;
        }
        else
        {
            std::cout << "加载失败\n"
                      << std::endl;
            return -1;
        }

        // 生成每一个站点的气象数据---->Vector<st_surfdata>
        CrtSurfData();

        // 生成CSV格式，“json,csv,xml”
        // strstr:当前字符串里是否含有指定的字符串
        if (strstr(argv[4], "xml") != 0)
            CrtSurfFile(argv[2], "xml");

        if (strstr(argv[4], "json") != 0)
            CrtSurfFile(argv[2], "json");

        if (strstr(argv[4], "csv") != 0)
            CrtSurfFile(argv[2], "csv");

            
    }
    else
    {
        // 日志失败
        printf("打开日志失败");
        return -1;
    }

    return 0;
}

bool LoadSTCode(const char *inifile)
{
    // 首先打开这个文件
    // 循环读
    // 分割
    // 写入一个结构体
    // 结构体存放到vector

    CCmdStr CmdStr;
    struct st_stcode stcode;

    if (File.Open(inifile, "r"))
    {
        char strBuffer[301];
        memset(strBuffer, 0, 301);

        // 初始化
        while (true)
        {
            // 读取，检查是否退出
            if (File.Fgets(strBuffer, 300, true))
            {
                // 切割字符串strBuffer,','和“,”
                CmdStr.SplitToCmd(strBuffer, ",", true);
                if (CmdStr.CmdCount() != 6)
                    continue;
                // 存放到机构提
                // bool GetValue(const int inum,char *value,const int ilen=0); // 字符串，ilen缺省值为0。

                CmdStr.GetValue(0, stcode.provname, 30); // 省
                CmdStr.GetValue(1, stcode.obtid, 10);    // 站号
                CmdStr.GetValue(2, stcode.obtname, 30);  // 站名
                CmdStr.GetValue(3, &stcode.lat);         // 纬度
                CmdStr.GetValue(4, &stcode.lon);         // 经度
                CmdStr.GetValue(5, &stcode.height);      // 海拔高度

                // 个人建议：用完之后，去清空，为下一次循环做准备
                logfile.Write(stcode.provname, stcode.obtid);
                vstcode.push_back(stcode);
                memset((void *)&stcode, 0, sizeof(struct st_stcode));
                // memset((void*) &stcode,0,301);
            }
            else
            {
                break;
            }
        }
        return true;
    }
    else
    {
        logfile.Write("读取站点参数数据失败\n");
        return false;
    }
}

void CrtSurfData()
{

    // 读取每一个站点，为每一个站点生成气象数据，然后存储到vector

    // 初始化种子
    srand(time(0));

    // 时间操作,"yyyymmddhh24miss"

    // memset(strddatetime, 0, 21);
    // LocalTime(strddatetime, "yyyymmddhh24miss");

    struct st_surfdata stsurfdata;
    memset(&stsurfdata, 0, sizeof(struct st_surfdata));
    for (size_t i = 0; i < vstcode.size(); i++)
    {
        // 生成每一个站点的气象参数
        strncpy(stsurfdata.obtid, vstcode[i].obtid, 11);
        strncpy(stsurfdata.ddatetime, strddatetime, 21);
        // 随机生成，存储
        stsurfdata.t = rand() % 351;             // 气温：单位，0.1摄氏度
        stsurfdata.p = rand() % 265 + 10000;     // 气压：0.1百帕
        stsurfdata.u = rand() % 100 + 1;         // 相对湿度，0-100之间的值。
        stsurfdata.wd = rand() % 360;            // 风向，0-360之间的值。
        stsurfdata.wf = rand() % 150;            // 风速：单位0.1m/s
        stsurfdata.r = rand() % 16;              // 降雨量：0.1mm
        stsurfdata.vis = rand() % 5001 + 100000; // 能见度：0.1米
        vsurfdata.push_back(stsurfdata);
        memset(&stsurfdata, 0, sizeof(struct st_surfdata));
    }
}

bool CrtSurfFile(const char *outpath, const char *datafmt)
{

    // 生成文件名：拼接文件名：Sprintf():拼接字符串：格式化拼接
    char strFileName[301];
    sprintf(strFileName, "%s/SURF_ZH_%s_%d.%s", outpath, strddatetime, getpid(), datafmt);

    // 打开文件

    if (File.OpenForRename(strFileName, "w"))
    {
        // 就循环写入参数
        // 写前文本
        // 当前写那种格式的文件
        if (strcmp(datafmt, "csv") == 0)
        {
            // 生成CSV格式
            File.Fprintf("站点代码,数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度\n");
            // 循环去写
            for (size_t i = 0; i < vsurfdata.size(); i++)
            {
                File.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\n", vsurfdata[i].obtid, vsurfdata[i].ddatetime, vsurfdata[i].t / 10.0, vsurfdata[i].p / 10.0, vsurfdata[i].u, vsurfdata[i].wd, vsurfdata[i].wf / 10.0, vsurfdata[i].r / 10.0, vsurfdata[i].vis / 10.0);
            }

            // 关闭文件
            File.CloseAndRename();
            UTime(strFileName,strddatetime);  // 修改文件的时间属性。
            logfile.Write("生成数据文件%s成功，数据时间%s，记录数%d。\n", strFileName, strddatetime, vsurfdata.size());
        }
        else if (strcmp(datafmt, "xml") == 0)
        {
            // 生成xml
            File.Fprintf("<data>\n");
            for (size_t i = 0; i < vsurfdata.size(); i++)
            {
                File.Fprintf("<obtid>%s</obtid><ddatetime>%s</ddatetime><t>%.1f</t><p>%.1f</p>"
                             "<u>%d</u><wd>%d</wd><wf>%.1f</wf><r>%.1f</r><vis>%.1f</vis><endl/>\n",
                             vsurfdata[i].obtid, vsurfdata[i].ddatetime, vsurfdata[i].t / 10.0, vsurfdata[i].p / 10.0,
                             vsurfdata[i].u, vsurfdata[i].wd, vsurfdata[i].wf / 10.0, vsurfdata[i].r / 10.0, vsurfdata[i].vis / 10.0);
            }
            File.Fprintf("</data>\n");
            File.CloseAndRename();
            UTime(strFileName,strddatetime);  // 修改文件的时间属性。
            logfile.Write("生成数据文件%s成功，数据时间%s，记录数%d。\n", strFileName, strddatetime, vsurfdata.size());
        }
        else
        {
            // 生成Json
            File.Fprintf("{\"data\":[\n");
            for (size_t i = 0; i < vsurfdata.size(); i++)
            {
                File.Fprintf("{\"obtid\":\"%s\",\"ddatetime\":\"%s\",\"t\":\"%.1f\",\"p\":\"%.1f\","
                             "\"u\":\"%d\",\"wd\":\"%d\",\"wf\":\"%.1f\",\"r\":\"%.1f\",\"vis\":\"%.1f\"}",
                             vsurfdata[i].obtid, vsurfdata[i].ddatetime, vsurfdata[i].t / 10.0, vsurfdata[i].p / 10.0,
                             vsurfdata[i].u, vsurfdata[i].wd, vsurfdata[i].wf / 10.0, vsurfdata[i].r / 10.0, vsurfdata[i].vis / 10.0);
                if (i < vsurfdata.size() - 1)
                    File.Fprintf(",\n");
                else
                    File.Fprintf("\n");
            }
            File.Fprintf("]}\n");
            File.CloseAndRename();
            UTime(strFileName,strddatetime);  // 修改文件的时间属性。
            logfile.Write("生成数据文件%s成功，数据时间%s，记录数%d。\n", strFileName, strddatetime, vsurfdata.size());
        }
    }
    else
    {
        // 关闭。输出日志
        logfile.Write("打开输出文件失败\n");
        return false;
    }

    return true;
}
void handle(int sig)
{
    printf("中断生成文件\n");
    exit(1);
}
